<template>
  <div class="x-editor">
    <textarea ref="refTinymce">
      {{ value }}
    </textarea>
    <div class="_word-count">{{ wordCount || 0 }}字</div>
    <div v-if="!value" class="_placeholder">{{ placeholder }}</div>
  </div>
</template>

<script lang="ts">
  import $http from '@/utils/http/axios'
  import { computed, defineComponent, reactive, toRefs, ref, onMounted } from 'vue'
  import { useMessage } from 'naive-ui'
  import tinymce from 'tinymce/tinymce'
  import 'tinymce/skins/ui/oxide/skin.min.css'
  import 'tinymce/themes/silver'
  import 'tinymce/models/dom'
  import 'tinymce/icons/default'
  import 'tinymce/plugins/image'
  import 'tinymce/plugins/media'
  import 'tinymce/plugins/wordcount'
  import 'tinymce/plugins/emoticons'
  import 'tinymce/plugins/emoticons/js/emojis'
  import 'tinymce/plugins/table'
  import 'tinymce/plugins/link'
  import 'tinymce/plugins/preview'

  export default defineComponent({
    name: 'XEditor',
    components: {},
    props: {
      value: {
        type: String,
        default: ''
      },
      placeholder: {
        type: String,
        default: '请输入内容'
      },
      setting: {
        type: Object,
        default: () => {}
      },
      disabled: {
        type: Boolean,
        default: false
      }
    },
    emits: ['update:value', 'change', 'init'],
    setup($props, { emit: $emit }) {
      const refTinymce = ref(null)
      const $state = reactive({
        ...toRefs($props),
        wordCount: 0,
        content: computed(() => $props.value)
      })
      const message = useMessage()

      onMounted(() => {
        tinymce.init({
          height: 500,
          menubar: false,
          skin: false,
          content_css: ['//alicdn.itaored.com/static/tinymce/tiny.css'],
          statusbar: false,
          target: refTinymce.value,
          language: 'zh-Hans',
          language_url: '//alicdn.itaored.com/static/tinymce/langs/zh-Hans.js',
          toolbar:
            'undo redo blocks fontsize backcolor forecolor bold italic underline numlist bullist link image media alignleft aligncenter alignright alignjustify emoticons table | indent outdent blockquote removeformat preview',
          plugins: 'image media wordcount emoticons table link preview',
          invalid_elements: 'input,textarea,style,body,script,button,radio,select,from',
          link_default_target: '_blank',
          image_uploadtab: true,
          images_file_types: 'jpg,svg,webp,png,gif,jpeg',
          file_picker_types: 'media',
          file_picker_callback: function (cb, value, meta) {
            // 视频上传
            if (meta.filetype == 'media') {
              const input = document.createElement('input')
              input.setAttribute('type', 'file')
              input.setAttribute('accept', 'video/*')
              input.onchange = async function () {
                const file = this.files[0]
                if (file.size > 100 * 1024 * 1024) {
                  message.warning('视频大小不能超过100M')
                  return
                }
                const formData = new FormData()
                formData.append('file', file)
                const response = await $http.uploadFiles(
                  {
                    url: '/api/product/media/upload',
                    data: {
                      mediaType: 2,
                      resourceType: 0
                    }
                  },
                  file
                )
                const data = await response.data
                cb(data.fileUrl, {
                  title: file.fileName
                })
              }
              input.click()
            }
          },
          images_upload_handler: (blobInfo: any) =>
            new Promise((resolve, reject) => {
              $http
                .uploadFiles(
                  {
                    url: '/api/product/media/upload',
                    data: {
                      mediaType: 1,
                      resourceType: 0
                    }
                  },
                  blobInfo.blob()
                )
                .then((res: any) => {
                  resolve(res.data.fileUrl)
                })
                .catch((err) => {
                  reject(err.message || err.msg)
                })
            }),
          // 品牌
          branding: false,
          setup: (editor: any) => {
            // 初始化
            editor.on('init', () => {
              $emit('init', editor)
              setWordCount(editor)
            })
            // 输入
            editor.on('input', () => {
              $emit('update:value', editor.getContent())
              $emit('change', editor)
              setWordCount(editor)
            })

            // 失焦
            editor.on('blur', () => {
              $emit('update:value', editor.getContent())
              $emit('change', editor)
              setWordCount(editor)
            })

            // keyup
            editor.on('keyup', () => {
              $emit('update:value', editor.getContent())
              $emit('change', editor)
              setWordCount(editor)
            })
          },
          ...$props.setting
        })
      })

      const setWordCount = (editor: any) => {
        // 按字符串计
        // console.log(wordcount.getCharacterCount())
        // 按单词计
        // console.log(wordcount.getWordCount())
        $state.wordCount = editor?.plugins.wordcount.body.getCharacterCount()
      }

      return {
        ...toRefs($state),
        refTinymce
      }
    }
  })
</script>

<style lang="scss">
  .x-editor {
    position: relative;
    ._word-count {
      position: absolute;
      right: 10px;
      bottom: 10px;
      font-size: 13px;
      background-color: #fff;
      padding: 0 2px;
      color: #999;
    }
    ._placeholder {
      position: absolute;
      left: 20px;
      top: 63px;
      color: #999;
      pointer-events: none;
    }
  }
</style>
